package com.base.pig.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.base.pig.dto.ScAlarmReportsDto;
import com.base.pig.dto.ScReportsManageDto;
import com.base.pig.entity.ScAlarmManager;
import com.base.pig.entity.ScConfigAddress;
import com.base.pig.entity.SysDictItem;
import com.base.pig.mapper.ScReportManageMapper;
import com.base.pig.service.ScReportsManageService;
import com.base.pig.util.Base64Util;
import com.base.pig.service.ScAlarmManagerService;
import com.base.pig.service.SysDictItemService;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ProjectName
 * @Package com.pig4cloud.pig.lab.service.impl
 * @ClassName ReportsManageServiceImpl
 * @Description 报表管理服务逻辑处理层
 * @Company lab
 * @Author wangw
 * @Date 2020/6/24 0024 10:08
 * @UpdateUser
 * @UpdateDate
 * @UpdateRemark
 * @Version 1.0.0
 */
@Service
@Slf4j
public class ScScReportsManageServiceImpl extends ServiceImpl<ScReportManageMapper, ScAlarmManager> implements ScReportsManageService {

    @Autowired
    private SysDictItemService sysDictItemService;

    @Autowired
    private ScAlarmManagerService scAlarmManagerService;

    @Autowired
    private Base64Util base64Util;

    @Autowired
    private ScConfigAddress scConfigAddress;

    static final String YEAR = "1";
    static final String MONTH = "2";
    static final String DAY = "3";

    @Override
    public List getDeviceAlarmReports(ScReportsManageDto scReportsManageDto) {
        // 根据设备类型(dict表中对应的value值==alarmManager表中的deviceType)报警次数重新组装数据
        List<SysDictItem> deviceList = sysDictItemService.getDictChildren("device_type");
        // 报警消息总数
        int amount = (int) scAlarmManagerService.count();
        List list = new ArrayList();
        // 创建一个数值格式化对象
        NumberFormat numberFormat = NumberFormat.getInstance();
        numberFormat.setMaximumFractionDigits(2);
        deviceList.forEach(device -> {
            QueryWrapper alarmWrapper = new QueryWrapper();
            if (StrUtil.isNotBlank(scReportsManageDto.getStartAlarmRecordTime())) {
                alarmWrapper.ge("alarm_time", scReportsManageDto.getStartAlarmRecordTime());
            }

            if (StrUtil.isNotBlank(scReportsManageDto.getEndAlarmRecordTime())) {
                alarmWrapper.le("alarm_time", scReportsManageDto.getEndAlarmRecordTime());
            }
            Map deviceMap = new HashMap();
            alarmWrapper.eq("device_type", device.getValue());
            int count = (int) scAlarmManagerService.count(alarmWrapper);
            deviceMap.put("deviceType", device.getValue());
            deviceMap.put("deviceName", device.getLabel());
            deviceMap.put("alarmCount", count);
            if(amount!=0)
                deviceMap.put("proportion", numberFormat.format((float) count / (float) amount * 100) + "%");
            else
                deviceMap.put("proportion","0%");
            list.add(deviceMap);
        });
        return list;
    }

    @Override
    public void export(HttpServletRequest request, HttpServletResponse response, ScReportsManageDto scReportsManageDto) {
        List list = getDeviceAlarmReports(scReportsManageDto);
        List rows = CollUtil.newArrayList(list);
        String fileName = "export.xlsx";    //  导出文件名称
        String filePath = scConfigAddress.getExportFilePath() + fileName;
        //通过工具类创建writer
        BigExcelWriter writer = ExcelUtil.getBigWriter(filePath);
        //自定义标题别名
        writer.addHeaderAlias("deviceName", "设备类型名称");
        writer.addHeaderAlias("deviceType", "设备类型编号");
        writer.addHeaderAlias("alarmCount", "报警次数");
        writer.addHeaderAlias("proportion", "占比");
        //一次性写出内容，使用默认样式，强制输出标题
        writer.write(rows, true);
        //关闭writer释放内存
        writer.close();
        try {
            base64Util.downFile(filePath, response);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        File file = new File(filePath);
        file.delete();
    }

    @Override
    public IPage getReports(ScReportsManageDto scReportsManageDto) {
        // 类型为全部
        QueryWrapper alarmDeviceWrapper = new QueryWrapper();
        if (StrUtil.isNotBlank(scReportsManageDto.getDeviceType())) {
            alarmDeviceWrapper.eq("device_type", scReportsManageDto.getDeviceType());
        }

        if (StrUtil.isNotBlank(scReportsManageDto.getSn())) {
            alarmDeviceWrapper.eq("sn", scReportsManageDto.getSn());
        }

        if (StrUtil.isNotBlank(scReportsManageDto.getStartAlarmRecordTime())) {
            alarmDeviceWrapper.ge("alarm_time", scReportsManageDto.getStartAlarmRecordTime());
        }
        if (StrUtil.isNotBlank(scReportsManageDto.getStartAlarmRecordTime())) {
            alarmDeviceWrapper.le("alarm_time", scReportsManageDto.getEndAlarmRecordTime());
        }

        Page page = new Page();
        if (StrUtil.isNotBlank(scReportsManageDto.getSize())) {
            page.setSize(Long.valueOf(scReportsManageDto.getSize()));
        }

        if (StrUtil.isNotBlank(scReportsManageDto.getCurrent())) {
            page.setCurrent(Long.valueOf(scReportsManageDto.getCurrent()));
        }
        alarmDeviceWrapper.groupBy("device_type");
        alarmDeviceWrapper.groupBy("sn");
        IPage<ScAlarmManager> iPage = scAlarmManagerService.page(page, alarmDeviceWrapper);
        return iPage;
    }

    @Override
    public Map getYearMonthReportsDetails(ScReportsManageDto scReportsManageDto) {

        QueryWrapper alarmWrapper = new QueryWrapper();
        if (StrUtil.isNotBlank(scReportsManageDto.getSn())) {
            alarmWrapper.eq("sn", scReportsManageDto.getSn());
        }

        if (StrUtil.isNotBlank(scReportsManageDto.getManufacturerNumber())) {
            alarmWrapper.eq("manufacturer_number", scReportsManageDto.getManufacturerNumber());
        }

        if (StrUtil.isNotBlank(scReportsManageDto.getStartAlarmRecordTime())) {
            alarmWrapper.ge("alarm_time", scReportsManageDto.getStartAlarmRecordTime());
        }

        if (StrUtil.isNotBlank(scReportsManageDto.getStartAlarmRecordTime())) {
            alarmWrapper.le("alarm_time", scReportsManageDto.getEndAlarmRecordTime());
        }
        scReportsManageDto.setStatus(true);
        Map map = new HashMap();
        try {
            map = recursion(scReportsManageDto, new ArrayList(),new ArrayList<>(),scReportsManageDto.getEndAlarmRecordTime());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * @param scReportsManageDto : 查看报表详情的参数对象
     * @param list               : 用于记录报表详情下方对应的图标数据
     * @param entityList         : 用于记录报警报表实体
     * @param endTime            : 用于中介递归条件的报警结束时间
     * @return
     * @Title 该方法用于递归查询报表所需要的数据
     * @Description
     * @author wangw
     * @date 2020/7/3 0003 16:44
     */
    public Map recursion(ScReportsManageDto scReportsManageDto, List list, List<ScAlarmReportsDto> entityList, String endTime) throws ParseException {
        Map resultMap = new HashMap();
        if (!scReportsManageDto.isStatus()) {
            return resultMap;
        }
        // 结合报警时间做出限制,准备递归
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        Calendar startDate = Calendar.getInstance();
        Calendar obj = Calendar.getInstance();
        startDate.setTime(simpleDateFormat.parse(scReportsManageDto.getStartAlarmRecordTime()));
        obj.setTime(simpleDateFormat.parse(scReportsManageDto.getStartAlarmRecordTime()));
        Calendar endDate = Calendar.getInstance();
        endDate.setTime(simpleDateFormat.parse(scReportsManageDto.getEndAlarmRecordTime()));

        Calendar endTimeCalendar = Calendar.getInstance();
        endTimeCalendar.setTime(simpleDateFormat.parse(endTime));
        // 开始逻辑处理->判断查询条件,查询数据信息
        Map map = new HashMap();
        QueryWrapper wrapper = new QueryWrapper();
        if (StrUtil.isNotBlank(scReportsManageDto.getSn())) {
            wrapper.eq("sn", scReportsManageDto.getSn());
        }
        if (StrUtil.isNotBlank(scReportsManageDto.getManufacturerNumber())) {
            wrapper.eq("manufacturer_number", scReportsManageDto.getManufacturerNumber());
        }
        // 递归开始,根据业务类型,时间后推x年或月
        if (YEAR.equals(scReportsManageDto.getBusinessType())) {
            // 获取时间段
            wrapper.ge("alarm_time", scReportsManageDto.getStartAlarmRecordTime());
            startDate.add(Calendar.YEAR, +1);
            String nextYear = simpleDateFormat.format(startDate.getTime());
            scReportsManageDto.setEndAlarmRecordTime(nextYear);
            wrapper.le("alarm_time", nextYear);
            // 分组条件
            long alarmCount = scAlarmManagerService.count(wrapper);
            wrapper.groupBy("sn,device_type");

            map.put(obj.get(Calendar.YEAR), alarmCount);
            list.add(map);

            ScAlarmManager scAlarmManager = scAlarmManagerService.getOne(wrapper);
            if (scAlarmManager != null) {
                ScAlarmReportsDto scAlarmReportsDto = new ScAlarmReportsDto();
                scAlarmReportsDto.setSn(scAlarmManager.getSn());
                scAlarmReportsDto.setDeviceType(scAlarmManager.getDeviceType());
                scAlarmReportsDto.setDeviceTypeName(scAlarmManager.getDeviceTypeName());
                scAlarmReportsDto.setManufacturerNumber(scAlarmManager.getManufacturerNumber());
                scAlarmReportsDto.setLocation(scAlarmManager.getLocation());
                scAlarmReportsDto.setAlarmCount((int) alarmCount);
                scAlarmReportsDto.setAlarmTime(String.valueOf(scAlarmManager.getAlarmTime()));
                entityList.add(scAlarmReportsDto);
            }

            System.out.println(simpleDateFormat.format(startDate.getTime()));
            System.out.println(endTime);
            if (!startDate.before(endTimeCalendar)) {
                scReportsManageDto.setStatus(false);
            }

            scReportsManageDto.setStartAlarmRecordTime(nextYear);
            recursion(scReportsManageDto, list, entityList,endTime);
        }

        // 再次特别说明: 这里需要对时间进行计算,结合业务需求,查询时间范围内的数据
        // 每次递归都意味着开始时间和结束时间会改变
        if (MONTH.equals(scReportsManageDto.getBusinessType())) {
            // 获取时间段
            wrapper.ge("alarm_time", scReportsManageDto.getStartAlarmRecordTime());
            startDate.add(Calendar.MONTH, +1);
            String nextYear = simpleDateFormat.format(startDate.getTime());
            scReportsManageDto.setEndAlarmRecordTime(nextYear);
            wrapper.le("alarm_time", nextYear);
            // 分组条件
            long alarmCount = scAlarmManagerService.count(wrapper);
            wrapper.groupBy("sn,device_type");
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
            map.put(format.format(obj.getTime()), alarmCount);
            list.add(map);

            ScAlarmManager scAlarmManager = scAlarmManagerService.getOne(wrapper);
            if (scAlarmManager != null) {
                ScAlarmReportsDto scAlarmReportsDto = new ScAlarmReportsDto();
                scAlarmReportsDto.setSn(scAlarmManager.getSn());
                scAlarmReportsDto.setDeviceType(scAlarmManager.getDeviceType());
                scAlarmReportsDto.setDeviceTypeName(scAlarmManager.getDeviceTypeName());
                scAlarmReportsDto.setManufacturerNumber(scAlarmManager.getManufacturerNumber());
                scAlarmReportsDto.setLocation(scAlarmManager.getLocation());
                scAlarmReportsDto.setAlarmCount((int) alarmCount);
                scAlarmReportsDto.setAlarmTime(String.valueOf(scAlarmManager.getAlarmTime()));
                entityList.add(scAlarmReportsDto);
            }
            System.out.println(simpleDateFormat.format(startDate.getTime()));
            System.out.println(endTime);
            if (!startDate.before(endTimeCalendar)) {
                scReportsManageDto.setStatus(false);
            }
            scReportsManageDto.setStartAlarmRecordTime(nextYear);
            recursion(scReportsManageDto, list, entityList,endTime);
        }

        resultMap.put("deviceAlarmInfo", entityList);
        resultMap.put("deviceAlarmReports", list);
        return resultMap;
    }

    @Override
    public IPage getDayReports(ScReportsManageDto scReportsManageDto) {
        // 因为日统计需要进行分页,与年/月返回体不一样,所以分开写
        Page page = new Page();
        QueryWrapper alarmWrapper = new QueryWrapper();
        if (StrUtil.isNotBlank(scReportsManageDto.getSn())) {
            alarmWrapper.eq("sn", scReportsManageDto.getSn());
        }
        if (StrUtil.isNotBlank(scReportsManageDto.getManufacturerNumber())) {
            alarmWrapper.eq("manufacturer_number", scReportsManageDto.getManufacturerNumber());
        }
        if (StrUtil.isNotBlank(scReportsManageDto.getStartAlarmRecordTime())) {
            alarmWrapper.ge("alarm_time", scReportsManageDto.getStartAlarmRecordTime());
        }
        if (StrUtil.isNotBlank(scReportsManageDto.getStartAlarmRecordTime())) {
            alarmWrapper.le("alarm_time", scReportsManageDto.getEndAlarmRecordTime());
        }
        if (StrUtil.isNotBlank(scReportsManageDto.getSize())) {
            page.setSize(Long.valueOf(scReportsManageDto.getSize()));
        }
        if (StrUtil.isNotBlank(scReportsManageDto.getCurrent())) {
            page.setCurrent(Long.valueOf(scReportsManageDto.getCurrent()));
        }
        IPage iPage = scAlarmManagerService.page(page, alarmWrapper);
        List<ScAlarmManager> list = iPage.getRecords();
        List<Map> mapList = list.stream().map(scAlarmManager -> {
            Map map = new HashMap();
            map.put("sn", scAlarmManager.getSn());
            map.put("manufacturerNumber", scAlarmManager.getManufacturerNumber());
            map.put("deviceType", scAlarmManager.getDeviceType());
            map.put("deviceName", scAlarmManager.getDeviceTypeName());
            map.put("location", scAlarmManager.getLocation());
            map.put("uploadTime", scAlarmManager.getGmtCreate());
            return map;
        }).collect(Collectors.toList());
        iPage.setRecords(mapList);
        return iPage;
    }
    @Override
    public Object getDayReportsDeviceInfo(ScReportsManageDto scReportsManageDto) {
        return  null;
    }
/*
    @Override
    public Object getDayReportsDeviceInfo(ScReportsManageDto scReportsManageDto) {
//        String airTempHumi = "a";
//        String digNoise = "2";
//        String flow = "3";
//        String gas = "4";
//        String harmfulGas = "5";
//        String liquidLevel = "6";
//        String location = "7";
//        String manholeCover = "8";
//        String rainFall = "9";
//        String waterQuality = "10";
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("device_type", scReportsManageDto.getDeviceType());
        queryWrapper.eq("sn", scReportsManageDto.getSn());
        queryWrapper.eq("manufacturer_number", scReportsManageDto.getManufacturerNumber());
        Long deviceId = scDeviceService.getOne(queryWrapper).getDeviceId();
        QueryWrapper deviceWrapper = new QueryWrapper();
        deviceWrapper.eq("device_id", deviceId);
        Object obj = null;
        switch (scReportsManageDto.getDeviceType()) {
            case ("1"):
                obj = scDeviceAirTemphumiMapper.selectOne(deviceWrapper);
                break;
            case ("2"):
                obj = scDeviceDignoiseMapper.selectOne(deviceWrapper);
                break;
            case ("3"):
                obj = scDeviceFlowMapper.selectOne(deviceWrapper);
                break;
            case ("4"):
                obj = scDeviceGasMapper.selectOne(deviceWrapper);
                break;
            case ("5"):
                obj = scDeviceHarmfulgasMapper.selectOne(deviceWrapper);
                break;
            case ("6"):
                obj = scDeviceLiquidlevelMapper.selectOne(deviceWrapper);
                break;
            case ("7"):
                obj = scDeviceLocationMapper.selectOne(deviceWrapper);
                break;
            case ("8"):
                obj = scDeviceManholecoverMapper.selectOne(deviceWrapper);
                break;
            case ("9"):
                obj = scDeviceRainfallMapper.selectOne(deviceWrapper);
                break;
            case ("10"):
                obj = scDeviceWaterqualityMapper.selectOne(deviceWrapper);
                break;
        }
        return obj;
    }

    @Autowired
    private ScDeviceService scDeviceService;

    @Autowired
    private ScDeviceAirTemphumiMapper scDeviceAirTemphumiMapper;

    @Autowired
    private ScDeviceDignoiseMapper scDeviceDignoiseMapper;

    @Autowired
    private ScDeviceFlowMapper scDeviceFlowMapper;

    @Autowired
    private ScDeviceGasMapper scDeviceGasMapper;

    @Autowired
    private ScDeviceHarmfulgasMapper scDeviceHarmfulgasMapper;

    @Autowired
    private ScDeviceLiquidlevelMapper scDeviceLiquidlevelMapper;

    @Autowired
    private ScDeviceLocationMapper scDeviceLocationMapper;

    @Autowired
    private ScDeviceManholecoverMapper scDeviceManholecoverMapper;

    @Autowired
    private ScDeviceRainfallMapper scDeviceRainfallMapper;

    @Autowired
    private ScDeviceWaterqualityMapper scDeviceWaterqualityMapper;
    */

}